﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MultiViewer.Network;
using System.Threading;
using MultiViewer.Display;
using System.Diagnostics;

namespace MultiViewer.Client
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class MainWindow : MultiViewerWindow
    {
        private TraceViewer traceViewer;

        public MainWindow()
        {
            InitializeComponent();
            traceViewer = new TraceViewer();
            Content = traceViewer;
#if DEBUG
            Trace.Listeners.Add(traceViewer.Listener);
#else
            Debug.Listeners.Add(traceViewer.Listener);
#endif
            Trace.WriteLine("MultiViewer.Client is starting...");
            Debug.WriteLine("MultiViewer is built in Debug mode");
        }

        protected override void OnClosed(EventArgs e)
        {
            if(Node != null)
                Node.Stop();
            base.OnClosed(e);
        }

        protected override void OnNodeConnected()
        {
            base.OnNodeConnected();
            Node.AddMessageHandler<InitDisplayRequest>(InitDisplayAsyncHandler);
            Node.AddMessageHandler<ShutdownRequest>(ShutdownAsyncHandler);
            Node.AddNotificationHandler<MouseNotification>(MouseNotificationHandler);
        }

        private object Invoke<T>(MessageHandler<T> handler, T argument)
        {
            object result = null;
            Dispatcher.Invoke(new SyncInvoker(delegate()
            {
                try
                {
                    result = handler(argument);
                }
                catch (Exception exc)
                {
                    Trace.WriteLine("Exception in " + typeof(T).Name + " handler: " + exc.Message);
                }
            }));
            return result;
        }

        private void BeginInvoke<T>(NotificationHandler<T> handler, T argument)
        {
            Dispatcher.BeginInvoke(new SyncInvoker(delegate()
            {
                try
                {
                    handler(argument);
                }
                catch (Exception exc)
                {
                    Trace.WriteLine("Exception in " + typeof(T).Name + " handler: " + exc.Message);
                }
            }));
        }

        private object InitDisplayAsyncHandler(InitDisplayRequest request)
        {
            return Invoke(InitDisplayHandler, request);
        }

        private object InitDisplayHandler(InitDisplayRequest request)
        {
            // TODO: Instead of MessageBox:
            // 1. Resize main window
            // 2. Replace Child object with content renderer
            MessageBox.Show(String.Format("InitDisplay: {0}x{1}x{2}", request.Width,request.Height, request.Fullscreen));
            return true;
        }

        private object ShutdownAsyncHandler(ShutdownRequest request)
        {
            return Invoke(ShutdownHandler, request);
        }

        private object ShutdownHandler(ShutdownRequest request)
        {
            Close();
            return true;
        }

        private void MouseNotificationAsyncHandler(MouseNotification e)
        {
            BeginInvoke(MouseNotificationHandler, e);
        }

        private void MouseNotificationHandler(MouseNotification e)
        {
            // TODO: handle mouse events properly
            Trace.WriteLine(String.Format("Mouse event: {0},{1}", e.X, e.Y));
        }
    }
}
